const INTROSPECT_DBUS_API_VERSION = 3;
const { loadInterfaceXML } = imports.misc.fileUtils;
+const { DBusSenderChecker } = imports.misc.util;
const IntrospectDBusIface = loadInterfaceXML('org.gnome.Shell.Introspect');
this._syncRunningApplications();
- this._allowlistMap = new Map();
- APP_ALLOWLIST.forEach(appName => {
- Gio.DBus.watch_name(Gio.BusType.SESSION,
- appName,
- Gio.BusNameWatcherFlags.NONE,
- (conn, name, owner) => this._allowlistMap.set(name, owner),
- (conn, name) => this._allowlistMap.delete(name));
- });
+ this._senderChecker = new DBusSenderChecker(APP_ALLOWLIST);
this._settings = St.Settings.get();
this._settings.connect('notify::enable-animations',
return app.get_windows().some(w => w.transient_for == null);
}
- _isSenderAllowed(sender) {
- return [...this._allowlistMap.values()].includes(sender);
- }
-
_getSandboxedAppId(app) {
let ids = app.get_windows().map(w => w.get_sandboxed_app_id());
return ids.find(id => id != null);
type == Meta.WindowType.UTILITY;
}
- _checkInvocation(invocation) {
- if (global.context.unsafe_mode)
- return;
-
- if (this._isSenderAllowed(invocation.get_sender()))
- return;
-
- throw new GLib.Error(Gio.DBusError,
- Gio.DBusError.ACCESS_DENIED,
- 'App introspection not allowed');
- }
-
GetRunningApplicationsAsync(params, invocation) {
try {
- this._checkInvocation(invocation);
+ this._senderChecker.checkInvocation(invocation);
} catch (e) {
invocation.return_gerror(e);
return;
let windowsList = {};
try {
- this._checkInvocation(invocation);
+ this._senderChecker.checkInvocation(invocation);
} catch (e) {
invocation.return_gerror(e);
return;
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported findUrls, spawn, spawnCommandLine, spawnApp, trySpawnCommandLine,
formatTime, formatTimeSpan, createTimeLabel, insertSorted,
- ensureActorVisibleInScrollView, wiggle, lerp, GNOMEversionCompare */
+ ensureActorVisibleInScrollView, wiggle, lerp, GNOMEversionCompare,
+ DBusSenderChecker */
const { Clutter, Gio, GLib, Shell, St, GnomeDesktop } = imports.gi;
const Gettext = imports.gettext;
return 0;
}
+
+var DBusSenderChecker = class {
+ /**
+ * @param {string[]} allowList - list of allowed well-known names
+ */
+ constructor(allowList) {
+ this._allowlistMap = new Map();
+
+ this._watchList = allowList.map(name => {
+ return Gio.DBus.watch_name(Gio.BusType.SESSION,
+ name,
+ Gio.BusNameWatcherFlags.NONE,
+ (conn_, name_, owner) => this._allowlistMap.set(name, owner),
+ () => this._allowlistMap.delete(name));
+ });
+ }
+
+ /**
+ * @param {string} sender - the bus name that invoked the checked method
+ * @returns {bool}
+ */
+ _isSenderAllowed(sender) {
+ return [...this._allowlistMap.values()].includes(sender);
+ }
+
+ /**
+ * Check whether the bus name that invoked @invocation maps
+ * to an entry in the allow list.
+ *
+ * @throws
+ * @param {Gio.DBusMethodInvocation} invocation - the invocation
+ * @returns {void}
+ */
+ checkInvocation(invocation) {
+ if (global.context.unsafe_mode)
+ return;
+
+ if (this._isSenderAllowed(invocation.get_sender()))
+ return;
+
+ throw new GLib.Error(Gio.DBusError,
+ Gio.DBusError.ACCESS_DENIED,
+ '%s is not allowed'.format(invocation.get_method_name()));
+ }
+
+ /**
+ * @returns {void}
+ */
+ destroy() {
+ for (const id in this._watchList)
+ Gio.DBus.unwatch_name(id);
+ this._watchList = [];
+ }
+};